package com.woniu.contorller;


import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.woniu.client.PermissionsClient;
import com.woniu.dto.*;
import com.woniu.exception.file.FileException;
import com.woniu.form.*;
import com.woniu.model.Result;
import com.woniu.model.TUser;
import com.woniu.params.*;

import com.woniu.server.TUserService;
import com.woniu.utils.JwtUtil;
import com.woniu.utils.utils.FileUtil;
import com.woniu.utils.utils.OSSUtil;
import com.woniu.utils.utils.RedisUtil;
import io.seata.core.context.RootContext;
import io.seata.spring.annotation.GlobalTransactional;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Positive;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author 吴彦祖
 * @since 2024年05月23日
 */
@RestController
@Validated
@RequestMapping("/tUser")
@Api(tags = "用户信息接口")
public class TUserController {
    @Autowired
    private TUserService tUserService;
    @Autowired
    private RedisUtil redisUtil;



    /**
     * 用户密码登录
     * @param form
     * @return
     */
    @PostMapping("/pwdLogin")
    @ApiOperation("密码登录")
    public Result<TUser> pwdLogin(@RequestBody @Validated UserLoginForm form) throws Exception {
        TUser  user = tUserService.pwdLogin(BeanUtil.toBean(form, UserLoginParam.class));
        return Result.newInstance(TUser.class).setMessage("登录成功").setData(user);
    }

    /**
     * 用户验证码登录
     * @param from
     * @return
     */
//    @PostMapping("/codeLogin")
//    @ApiOperation("用户验证码登录")
//    public Result<TUser> codeLogin(@RequestBody @Validated CodeLoginFrom from){
//        TUser user =  tUserService.codeLogin(BeanUtil.toBean(from, CodeLoginParam.class));
//        return Result.newInstance(TUser.class).setMessage("登录成功").setData(user);
//    }

    /**
     * 发送注册验证码
     * @param mobile
     * @return
     * @throws Exception
     */
    @GetMapping("/sendRegisterCode/{mobile}")
    @ApiOperation("发送注册验证码")
    public Result<String> sendRegisterCode(@ApiParam(name = "mobile",value = "手机号") @PathVariable("mobile")
                                               @NotBlank(message = "手机号码不能为空")
                                                @Pattern(regexp = "\\d{11}",message = "手机号码必须是11位")
                                               String mobile) throws Exception {
        tUserService.sendRegisterCode(mobile);
        return Result.newInstance(String.class).setMessage("发送成功");
    }

    /**
     * 验证码注册
     * @param from
     * @return
     * @throws Exception
     */
    @PostMapping("/codeRegister")
    @ApiOperation("验证码注册")
    public Result<UserRegisterDto> registerByCode(@RequestBody @Validated CodeRegisterFrom from) throws Exception {
        UserRegisterDto dto =  tUserService.registerByCode(BeanUtil.toBean(from, CodeRegisterParam.class));
        return Result.newInstance(UserRegisterDto.class).setMessage("注册成功").setData(dto);
    }

    /**
     * 收藏商品
     * @param goodsId 商品id
     * @param token 用户token
     * @return
     * @throws Exception
     */
    @GetMapping("/collect")
    @ApiOperation("用户收藏积分商品")
    public Result<String> collect(@ApiParam(name = "goodsId",value = "商品id")  @NotNull(message = "goodsId不能为空") @Positive(message = "goodsId必须是正整数") @RequestParam("goodsId") Integer goodsId, @RequestHeader String token) throws Exception {
        String refreshToken = redisUtil.get(token);
        int userId = Integer.parseInt(JwtUtil.parseToken(refreshToken,JwtUtil.userSecret).get("id").toString());
//        System.out.println(userId);
//        System.out.println("我是控制层的数据对象##########");
//        System.out.println(goodsId);
        tUserService.collect(goodsId,userId);
        return Result.newInstance(String.class).setMessage("收藏图书成功");
    }

    /**
     * 用户取消收藏
     * @param goodsId 商品id
     * @param token 用户token
     * @return
     * @throws Exception
     */
    @GetMapping("/delCollect")
    @ApiOperation("用户取消收藏商品")
    public Result<String> delCollect(@ApiParam(name = "goodsId",value = "商品id")
                                         @NotNull(message = "goodsId不能为空")
                                         @Positive(message = "goodsId必须是正整数")
                                         @RequestParam("goodsId")
                                         Integer goodsId,
                                     @RequestHeader String token) throws Exception {
        String refreshToken = redisUtil.get(token);
        int userId = Integer.parseInt(JwtUtil.parseUserToken(refreshToken).get("id").toString());
        tUserService.delCollect(goodsId,userId);
        return Result.newInstance(String.class).setMessage("取消收藏商品成功");
    }

    /**
     * 查看我的收藏
     * @param pageNum 第几页
     * @param pageSize 每页条数
     * @param token 用户token
     * @return
     */
    @GetMapping("/myCollect")
    @ApiOperation("查看我的收藏")
    public Result<Page<GoodsDto>> myCollect(@ApiParam(name = "pageNum",value = "第几页")
                                            @RequestParam(value = "pageNum", defaultValue = "1")
                                            Integer pageNum,
                                            @RequestParam(value = "pageSize", defaultValue = "10")
                                            @ApiParam(name = "pageSize",value = "每页记录数")
                                            Integer pageSize,
                                            @RequestHeader String token) throws Exception {
        String refreshToken = redisUtil.get(token);
        //System.out.println(refreshToken);
        int userId = Integer.parseInt(JwtUtil.parseUserToken(refreshToken).get("id").toString());
        Page<GoodsDto> page = tUserService.myCollect(pageNum,pageSize,userId);
        return Result.newPageInstance(GoodsDto.class).setData(page).setMessage("查询我的收藏成功");
    }

    /**
     * 用户添加商品进入 购物车
     * @param form 商品id 和数量
     * @param token
     * @return
     * @throws Exception
     */
    @PostMapping("/addShopping")
    @ApiOperation("添加商品购物车")
    public Result<String> addShopping(@RequestBody @Validated AddShoppingForm form, @RequestHeader String token) throws Exception {
        String refreshToken = redisUtil.get(token);
        int userId = Integer.parseInt(JwtUtil.parseUserToken(refreshToken).get("id").toString());
        AddShoppingParam param = BeanUtil.toBean(form, AddShoppingParam.class);
        param.setUserId(userId);
        tUserService.addShopping(param);
        return Result.newInstance(String.class).setMessage("添加商品进购物车成功");
    }

    /**
     * 删除购物车的商品
     * @param ids 商品id
     * @param token
     * @return
     * @throws Exception
     */
    @PostMapping("/delShopping")
    @ApiOperation("移除购物车的某个商品")
    public Result<String> delShopping(@ApiParam(name = "ids",value = "商品id集合") @RequestBody @NotNull(message = "商品集合不能为空") List<Integer> ids, @RequestHeader String token) throws Exception {
        if (ids==null){
            return Result.newInstance(String.class).setMessage("ids不能为空").setCode(500);
        }
        String refreshToken = redisUtil.get(token);
        int userId = Integer.parseInt(JwtUtil.parseUserToken(refreshToken).get("id").toString());
        tUserService.delShopping(ids,userId);
        return Result.newInstance(String.class).setMessage("移除购物车商品成功");
    }


    /**
     * 分页查询购物车 数据
     * @param pageNum 第几页
     * @param pageSize 每页几条数据
     * @param token
     * @return
     * @throws Exception
     */
    @GetMapping("/selAllShopping")
    @ApiOperation("分页查询购物车数据")
    public Result<Page<Map<Object, Object>>> selAllShopping(
            @ApiParam(name = "pageNum",value = "第几页")
            @RequestParam(value = "pageNum",required = true ,defaultValue = "1")
            Integer pageNum,
            @ApiParam(name = "pageSize",value = "每页记录数")
            @RequestParam(value = "pageNum",required = true,defaultValue = "10")
            Integer pageSize,
            @RequestHeader String token) throws Exception {
        String refreshToken = redisUtil.get(token);
        int userId = Integer.parseInt(JwtUtil.parseUserToken(refreshToken).get("id").toString());
        Page<Map<Object, Object>> page = tUserService.selAllShopping(pageNum, pageSize, userId);
        return Result.newPageMapInstance(Object.class).setMessage("查询购物车信息成功").setData(page);
    }

    /**
     * 修改购物车某件商品数量
     * @param from
     * @param token
     * @return
     * @throws Exception
     */
    @PostMapping("/modifyShopping")
    @ApiOperation("修改购物车商品数量")
    public Result<String> modifyShopping(@RequestBody @Validated ModifyShoppingForm from, @RequestHeader String token) throws Exception {
        String refreshToken = redisUtil.get(token);
        int userId = Integer.parseInt(JwtUtil.parseUserToken(refreshToken).get("id").toString());
        ModifyShoppingParam param = BeanUtil.toBean(from, ModifyShoppingParam.class);
        param.setUserId(userId);
        tUserService.modifyShopping(param);
        return Result.newInstance(String.class).setMessage("修改购物车某件商品数量成功");
    }

    /**
     * 实名认证接口
     * @param img 身份证图片
     * @return
     */
    @PostMapping("/authentication")
    @ApiOperation("实名认证接口(上传身份证)")
    public Result<TUser> authentication(@NotNull(message = "图书数据不能为空") MultipartFile img,@RequestHeader String token) throws Exception {
        String refreshToken = redisUtil.get(token);
        int userId = Integer.parseInt(JwtUtil.parseUserToken(refreshToken).get("id").toString());
         TUser tUser =  tUserService.authentication(img,userId);
         return Result.newInstance(TUser.class).setMessage("认证成功").setData(tUser);
    }

    /**
     * 用户退出登录
     * @param token 用户token
     * @return
     * @throws Exception
     */
    @GetMapping("/quit")
    @ApiOperation("退出登录")
    public Result<String> quit(@RequestHeader String token) throws Exception {
        redisUtil.del(token);
        return Result.newInstance(String.class).setMessage("退出登录");
    }

    /**
     * 上传头像
     * @param image 图片数据
     * @return
     * @throws Exception
     */
//    @PostMapping("/uploadImg")
//    @ApiOperation("上传头像")
//    public Result<String> uploadImg(@NotNull(message = "图书数据不能为空") MultipartFile image,@RequestHeader String token) throws Exception {
//
//        String refreshToken = redisUtil.get(token);
//        int userId = Integer.parseInt(JwtUtil.parseUserToken(refreshToken).get("id").toString());
//        String filePath =  tUserService.uploadImg(image,userId);
//        return Result.newInstance(String.class).setData(filePath).setMessage("上传成功");
//    }

    /**
     * 修改头像
     * @param image 新头像数据
     * @return 新头像地址
     * @throws Exception
     */
    @PostMapping("/modifyImg")
    @ApiOperation("修改头像")
    public Result<String> modifyImg(@NotNull MultipartFile image,
                                    @RequestHeader String token) throws Exception {
        String refreshToken = redisUtil.get(token);
        int userId = Integer.parseInt(JwtUtil.parseUserToken(refreshToken).get("id").toString());
        String filePath =  tUserService.modifyImg(image,userId);
        return Result.newInstance(String.class).setData(filePath);
    }

    /**
     * 修改个人信息
     * @param form 修改个人信息的form 数据
     * @return 返回被修改后的用户信息
     */
    @PostMapping("/modifyMyInfo")
    @ApiOperation("修改个人信息")
    public Result<TUser> modifyMyInfo(@RequestBody @Validated ModifyMyInfoForm form,@RequestHeader String token) throws Exception {
        String refreshToken = redisUtil.get(token);
        int userId = Integer.parseInt(JwtUtil.parseUserToken(refreshToken).get("id").toString());
        ModifyMyInfoParam param = BeanUtil.toBean(form, ModifyMyInfoParam.class);
        param.setUserId(userId);
        TUser tUser = tUserService.modifyMyInfo(param);
        return Result.newInstance(TUser.class).setData(tUser).setMessage("修改个人信息成功");
    }

    /**
     * 修改密码
     * @param form 修改密码所需的form数据
     * @param token 用户token
     * @return
     * @throws Exception
     */
    @PostMapping("/modifyPwd")
    @ApiOperation("修改密码")
    public Result<String> modifyPwd(@RequestBody @Validated ModifyPwdForm form,@RequestHeader String token) throws Exception {
        String refreshToken = redisUtil.get(token);
        int userId = Integer.parseInt(JwtUtil.parseUserToken(refreshToken).get("id").toString());
        ModifyPwdParam param = BeanUtil.toBean(form, ModifyPwdParam.class);
        param.setUserId(userId);
        tUserService.modifyPwd(param);
        redisUtil.del(token);
        return Result.newInstance(String.class).setMessage("修改密码成功,请重新登录");
    }

    /**
     * 根据id查询用户
     * @param userId 用户id
     * @return
     */
    @GetMapping("/userById/{userId}.api")
    @ApiOperation("根据id查询用户")
    public Result<TUser> userById(@ApiParam(name = "userId",value = "用户id") @PathVariable("userId")
                                      @NotNull(message = "用户id不能为空")
                                      @Positive(message = "用户id必须是正整数")
                                      Long userId){
        return Result.newInstance(TUser.class).setMessage("根据id查询用户成功").setData(tUserService.getById(userId));
    }

    /**
     * 根据用户id添加积分
     * @param form
     * @return
     */
    @PostMapping("/addCredibility.api")
    @ApiOperation("修改用户信誉分")
    public Result<TUser> addCredibility(@RequestBody @Validated AddCredibilityForm form){
        TUser user = tUserService.addCredibility(BeanUtil.toBean(form,AddCredibilityParam.class));
        return Result.newInstance(TUser.class).setData(user);
    }

    /**
     * 修改用户积分
     * @param userId 用户id
     * @param score 要修改的积分
     * @return
     */
    @GetMapping("/modifyScore.api/{userId}/{score}")
    @ApiOperation("修改用户积分")
    public Result<TUser> modifyScore(@PathVariable("userId") Integer userId, @PathVariable("score") BigDecimal score) throws Exception {
        TUser user = tUserService.getById(userId);
        if (user==null) {
            return Result.newInstance(TUser.class).setCode(500).setMessage("用户不存在");
        }
        if (user.getState()!=0){
            return Result.newInstance(TUser.class).setCode(500).setMessage("用户状态异常");
        }
        user.setScore(user.getScore().add(score));
        tUserService.updateById(user);
        return Result.newInstance(TUser.class).setData(user).setMessage("修改用户积分成功");
    }

    /**
     * 根据账号id查询用户
     * @param accountId 用户账号id
     * @return
     */
    @GetMapping("/byAccountId/{accountId}")
    @ApiOperation("根据账号id查询用户")
    public Result<TUser> byAliPayUsername(@PathVariable("accountId") Long accountId){
        TUser tUser = tUserService.getOne(new QueryWrapper<TUser>().eq("account_id", accountId));
        return Result.newInstance(TUser.class).setData(tUser);
    }
    @GetMapping("/myInfo")
    @ApiOperation("查看个人信息")
    public Result<TUser> myInfo(@RequestHeader String token) throws Exception {
        String refreshToken = redisUtil.get(token);
        int userId = Integer.parseInt(JwtUtil.parseUserToken(refreshToken).get("id").toString());
        TUser user = tUserService.getById(userId);
        if (user==null) throw new Exception("该用户还未注册");
        return Result.newInstance(TUser.class).setData(user);
    }


    /**
     * 用户查询自己的订单详情
     * @return list用户自己的订单
     */
    @GetMapping("/checkMyOrder")
    @ApiOperation("用户查询我的订单")
    public Result<List<OrderDto>> checkMyOrder(@RequestHeader String token) throws Exception {
        String refreshToken = redisUtil.get(token);
        int id = Integer.parseInt(JwtUtil.parseUserToken(refreshToken).get("accountId").toString());
         List<OrderDto>  list= tUserService.checkMyOrder(id);
        return Result.newListInstance(OrderDto.class).setData(list).setMessage("查看我的订单成功");
    }

    /**
     * 用户查询自己的订单详情
     * @return list用户自己的订单详情
     */
    @GetMapping("/checkMyOrderDetail/{orderNum}")
    @ApiOperation("用户查询自己的订单详情")
    public Result<List<OrderDetailsDto>> checkMyOrderDetail(@RequestHeader String token,@PathVariable("orderNum") String orderNum) throws Exception {
        String refreshToken = redisUtil.get(token);
        int id = Integer.parseInt(JwtUtil.parseUserToken(refreshToken).get("accountId").toString());
        List<OrderDetailsDto>  list= tUserService.checkMyOrderDetail(id,orderNum);
        return Result.newListInstance(OrderDetailsDto.class).setData(list).setMessage("查看我的订单成功");
    }

    /**
     * 用户查询所有垃圾类别
     * @return list垃圾类别
     */
    @GetMapping("/checkJunkType")
    @ApiOperation("用户查询所有垃圾类别")
    public Result<List<JunkTypeDto>> checkJunkType(@RequestHeader String token) throws Exception {
        String refreshToken = redisUtil.get(token);
        int id = Integer.parseInt(JwtUtil.parseUserToken(refreshToken).get("accountId").toString());
        List<JunkTypeDto>  list= tUserService.checkJunkType();
        return Result.newListInstance(JunkTypeDto.class).setData(list).setMessage("查询所有垃圾类别成功");
    }

    /**
     * 上传图片
     */
    @ApiOperation("用户上传图片")
    @PostMapping("/uploadImage")
    public Result<String> uploadPhoto(MultipartFile image,@RequestHeader("token") String token) throws Exception {
        String refreshToken = redisUtil.get(token);
        JwtUtil.parseEmployToken(refreshToken);

        if (!FileUtil.isImageFile(image.getInputStream())){
            throw  new FileException(9999,"文件类型错误");
        }
        String oldName = image.getOriginalFilename();
        String suffix = oldName.substring(oldName.lastIndexOf("."));
        String fileName = UUID.randomUUID().toString();

        String filePath = OSSUtil.uploadFile(image.getInputStream(),   fileName+suffix, "jinaisen");
        return Result.newInstance(String.class).setData(filePath).setMessage("上传图片成功");
    }
}

